#include "hashTable.h"


//Constructor
hashTable::hashTable()
{
	elements = 0;
}


//Return true if the hash table is empty
bool hashTable::empty()
{
	return elements == 0;
}


//Allocates memory for the array of the hash table
void hashTable::allocate(int width, int height)
{
	size = width*height;
	this->width = width;
	array = new Node*[size];
	for(int i = 0; i < size; i++) *(array + i) = 0;
}


//Free the memory allocated
void hashTable::freeNodes()
{
	delete array;
}


//Remove the node from the hash table and add it to it again
void hashTable::modifyNode(Node** item)
{
	Node* node = *item;

	//Remove the node
	remove(item);

	//Add the node
	addNode(node);
}


//Look for a node with coordinates x, y in the hash table
//If found, returns a pointer to the node and a pointer to its position in the array
std::pair<Node**, Node*> hashTable::findNode(int x, int y)
{
	std::pair<Node**, Node*> p;

	//Obtain the hash value
	int hash = hashFunction(x, y);

	//If the element is not in the hash table
	if(*(array + hash) == 0)
	{
		p.first = 0;
		p.second = 0;
	}
	else
	{
		p.first = array + hash;
		p.second = *(array + hash);
	}

	return p;
}


//Returns the node with lowest cost in the hash table
Node* hashTable::selectNodeLowestScore()
{
	Node* node = 0;
	Node** item = 0;

	for(int i = 0; i < size; i++)
	{
		if(*(array + i) != 0)
		{
			if(node)
			{
				if((*(array + i))->getF() < node->getF())
				{
					node = *(array + i);
					item = array + i;
				}
			}
			else
			{
				node = *(array + i);
				item = array + i;
			}
		}
	}

	remove(item);
	return node;
}


//Remove the pointer to node stored in *item
void hashTable::remove(Node** item)
{
	*item = 0;

	elements--;
}


//Add the node to the hash table in the position of the array that corresponds to
//its hash function
void hashTable::addNode(Node* node)
{
	//Obtain the hash function
	int hash = hashFunction(node->getX(), node->getY());

	//Store it
	*(array + hash) = node;

	elements++;
}


//Hash function
int hashTable::hashFunction(int x, int y)
{
	return x + y * width;
}